/**
 * 	Revised2011XMLReader.java
 *
 *  This file is part of the PDFGen Syllabus Formatter Project.
 *  Copyright (C) 2012  Gian Fontanilla
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.dlsu.pdfgen.io;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.dlsu.pdfgen.exceptions.InvalidXMLFileFormatException;
import org.dlsu.pdfgen.gui.ErrorFrame;
import org.dlsu.pdfgen.struct.Revised2011Syllabus;
import org.dlsu.pdfgen.struct.Syllabus;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Reads a properly formatted XML file. A singleton implementation - thus cannot
 * be instantiated. Use the static method <CODE>getInstance()</CODE> instead.
 * 
 * @author Michelle Ormoc
 * @see Revised2011Syllabus
 */

public class Revised2011XMLReader extends XMLReader{

	/**
	 * Private constructor. Necessary to prevent this class from being
	 * instantiated elsewhere.
	 */
	private Revised2011XMLReader() {
		super();
	}

	private static class SingletonRevised2011XMLReader {

		/** The singleton instance attribute */
		public static final Revised2011XMLReader INSTANCE = new Revised2011XMLReader();
	}

	/**
	 * Returns the singleton instance of the singleton.
	 * 
	 * @return The singleton instance of this class
	 */
	public static Revised2011XMLReader getInstance() {
		return SingletonRevised2011XMLReader.INSTANCE;
	}

	/**
	 * Reads an XML file containing syllabus information and creates a
	 * <CODE>Syllabus</CODE> object based on what was read.
	 * 
	 * @param fileName
	 *            The input XML file
	 * @return The resulting <CODE>Syllabus</CODE> object
	 */
	public Revised2011Syllabus readSyllabus(String fileName)
			throws InvalidXMLFileFormatException {

		// Syllabus object to be returned later
		Revised2011Syllabus s = new Revised2011Syllabus();

		try {
			File file = new File(fileName);
			System.out.println(file.getName());
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(file);
			doc.getDocumentElement().normalize();

			NodeList nodeLst;

			nodeLst = doc.getElementsByTagName("syllabus");
			if (nodeLst == null)
				throw new InvalidXMLFileFormatException();

			nodeLst = doc.getElementsByTagName("college");
			s.setCollege(nodeLst.item(0).getTextContent());
			
			nodeLst = doc.getElementsByTagName("code");
			s.setCourseCode(nodeLst.item(0).getTextContent());

			nodeLst = doc.getElementsByTagName("department");
			s.setDepartment(nodeLst.item(0).getTextContent());
			
			nodeLst = doc.getElementsByTagName("faculty");
			s.setFaculty(nodeLst.item(0).getTextContent());

			nodeLst = doc.getElementsByTagName("coursedesc");
			s.setCourseDesc(nodeLst.item(0).getTextContent());			
			
			nodeLst = doc.getElementsByTagName("time");
			s.setTime(nodeLst.item(0).getTextContent());

			nodeLst = doc.getElementsByTagName("room");
			s.setRoom(nodeLst.item(0).getTextContent());
			
			nodeLst = doc.getElementsByTagName("los");
			{
				Element node = (Element) nodeLst.item(0);
				s.setLearningOutcomeDescription(node.getElementsByTagName("learningdesc")
						.item(0).getTextContent());
				
				NodeList learning = node.getElementsByTagName("lo");
				for (int i = 0; i < learning.getLength(); i++) {
					s.getLearningOutcome().add(learning.item(i).getTextContent());
				}
			}
			
			nodeLst = doc.getElementsByTagName("finaloutcomes");
			{
				Element node = (Element) nodeLst.item(0);
				s.setFinalCourseOutputDescription(node.getElementsByTagName("finaldesc")
						.item(0).getTextContent());
				
				NodeList finalOutcome = node.getElementsByTagName("finaloutcome");;
				for (int i = 0; i < finalOutcome.getLength(); i++) {

					if (finalOutcome.item(i) instanceof Element) {

						Element nodeElement = (Element) finalOutcome.item(i);
						s.getFinalCourseOutput().add(
								s.createFinalOutput(
										nodeElement
												.getElementsByTagName("lo")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("output")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("date")
												.item(0).getTextContent()

								));
					}
				}
			}
			
			nodeLst = doc.getElementsByTagName("rubrics");
			{
				Element node = (Element) nodeLst.item(0);
				s.setRubricDescription(node.getElementsByTagName("rubricdesc")
						.item(0).getTextContent());
				
				NodeList rubric = node.getElementsByTagName("rubric");;
				for (int i = 0; i < rubric.getLength(); i++) {

					if (rubric.item(i) instanceof Element) {

						Element nodeElement = (Element) rubric.item(i);
						s.getRubric().add(
								s.createRubricAssessment(
										nodeElement
												.getElementsByTagName("criteria")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("exemplary")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("satisfactory")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("developing")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("beginning")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("rating")
												.item(0).getTextContent()

								));
					}
				}
			}
			
			nodeLst = doc.getElementsByTagName("others");
			{
				Element node = (Element) nodeLst.item(0);
				s.setOtherRequirementsDescription(node.getElementsByTagName("otherdesc")
						.item(0).getTextContent());
				
				s.setRequirementListType(((Element) nodeLst.item(0))
						.getAttribute("listType"));

				NodeList others = node.getElementsByTagName("other");
				for (int i = 0; i < others.getLength(); i++) {
					s.getOtherRequirements().add(others.item(i).getTextContent());
				}
			}
			
			nodeLst = doc.getElementsByTagName("gradings");
			{
				Element node = (Element) nodeLst.item(0);
				s.setGradingSystemDescription(node.getElementsByTagName("gradingdesc")
						.item(0).getTextContent());

				NodeList grading = node.getElementsByTagName("grading");
				for (int i = 0; i < grading.getLength(); i++) {
					s.getGradingSystem().add(grading.item(i).getTextContent());
				}
			}

			
			nodeLst = doc.getElementsByTagName("learningplans");
			{
				Element node = (Element) nodeLst.item(0);
				s.setLearningPlanDescription(node.getElementsByTagName("learningplandesc")
						.item(0).getTextContent());
				
				NodeList plan = node.getElementsByTagName("learningplan");;
				for (int i = 0; i < plan.getLength(); i++) {

					if (plan.item(i) instanceof Element) {

						Element nodeElement = (Element) plan.item(i);
						s.getLearningPlan().add(
								s.createLearningPlan(
										nodeElement
												.getElementsByTagName("lo")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("topic")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("week")
												.item(0).getTextContent(),
										nodeElement
												.getElementsByTagName("activities")
												.item(0).getTextContent()

								));
					}
				}
			}
			
			nodeLst = doc.getElementsByTagName("references");
			{
				Element node = (Element) nodeLst.item(0);
				s.setReferenceDescription(node.getElementsByTagName("refdesc")
						.item(0).getTextContent());
				
				s.setReferenceListType(((Element) nodeLst.item(0))
						.getAttribute("listType"));

				NodeList ref = node.getElementsByTagName("ref");
				for (int i = 0; i < ref.getLength(); i++) {
					s.getReferences().add(ref.item(i).getTextContent());
				}
			}
			
			nodeLst = doc.getElementsByTagName("online");
			{
				Element node = (Element) nodeLst.item(0);
				s.setOnlineResourcesDescription(node.getElementsByTagName("onlinedesc")
						.item(0).getTextContent());
				
				s.setOnlineResourceListType(((Element) nodeLst.item(0))
						.getAttribute("listType"));

				NodeList res = node.getElementsByTagName("resource");
				for (int i = 0; i < res.getLength(); i++) {
					s.getOnlineResources().add(res.item(i).getTextContent());
				}
			}
			
			nodeLst = doc.getElementsByTagName("policies");
			{
				Element node = (Element) nodeLst.item(0);
				s.setClassPolicyDescription(node.getElementsByTagName("policydesc")
						.item(0).getTextContent());
				
				s.setClassPolicyListType(((Element) nodeLst.item(0))
						.getAttribute("listType"));

				NodeList policy = node.getElementsByTagName("policy");
				for (int i = 0; i < policy.getLength(); i++) {
					s.getClassPolicy().add(policy.item(i).getTextContent());
				}
			}
		} catch (NullPointerException e) {
			e.printStackTrace();
			new ErrorFrame(e.getLocalizedMessage()).show();
			throw new InvalidXMLFileFormatException();
		} catch (org.xml.sax.SAXParseException e) {
			e.printStackTrace();
			new ErrorFrame("Error on file : " + e.getSystemId() + "\n\n"
					+ e.getLocalizedMessage()).show();
			throw new InvalidXMLFileFormatException();
		} catch (Exception e) {
			e.printStackTrace();

		}
		return s;
	}
}
